/**
1、下载全局http-server
2、开启 htpt-server
3、 安装vetur vue vscode snippets  
4、vue的设计思想
    1、设计思想
        1、数据驱动应用
        2、mvvm模式的践行者
    2、vue和model、和视图的关系
        1、用来展示下一个vue程序它应该所处的角色和它的作用，它的设计思想是什么，要完成什么任务
        2、中间这个绿色的大盒子，这个就是vue核心要完成的思想，我们的所有功能都封装在里面，viewdom
        3、vue最重要的功能就是完成viewdom这个功能，它还顺带把vue这一层也给实现了
    3、数据驱动
        1、mvvm三个要素，数据驱动是不是要实现响应式，改数据页面就会变化，这叫数据驱动
        2、那么界面怎么知道发生变化，一定是知道数据发生了变化，这就是数据响应式
    4、模板引擎呢，
        1、vue怎么知道视图里面的东西呢，因为我刚才写代码的时候，明明写的是这个表达式，怎么做的，怎么把这个值替换上
        2、这就涉及到模板引擎的解析了。
    5、渲染的问题，
        1、vue是怎么把这个模板转换成HTML的，工作的时候，这段模板实际上会被vue转换成一个js函数我们称之为渲染函数
        2、那么将来数据发生变化的时候，我们会重新执行渲染函数，得到最新的结果。得到的结果就是传说中的虚拟dom
        3、那么我们要做的事情就是把虚拟dom再变成一个真实的dom，这样的一个过程，它就是一个vue的基本工作原理
    6、vue核心思想
        1、data里的值，来源于服务器，绑定到视图上，视图改变，反作用于model，中间不经过dom操作
        2、data里面有一个数据，这就是model，它现在是写死的值，将来有可能来自服务器，作为vue，是不关心它的来源，我只是用来修改它
        3、它变了，我要改界面，界面变了，要影响它，我要对它反作用
        4、vue的核心作用，中间层，连接我们的数据，以及我们的视图，视图就是我们大家看到的这一层，HTML
        5、中间这一层，它可以把这个数据通过大家看到的响应式来进行数据绑定，data bindings,绑定到视图中，
        6、data 里的msg  html中的{{msg}}
        7、将来呢，如果这个数据发生变化，定时器发生变化，更新它，界面中用户有可能有一些事件，比如我点击事件，又或者说其它的一些事件
        8、总之，这些事件又可以反作用于，让用户可以修改数据模型
        9、所以呢，大家来看，一正一反，通过中间层vue这个中间层，做一个桥梁，避免用户直接接触dom,这样大幅提高用户的开发效率
        10、这就是vue它的核心思想
5、列表渲染
    1、用v-for指令来实现，使用item in items，这种形式来表示我要遍历的这个具体的数据，然后我拿出每个单个的数据从而方便我展示
    2、数据，
6、表单输入绑定
    1、我们再界面中如何处理用户的一些输入行为，form表单的一些输入项的绑定，这里要了解的是双向绑定，自然而然是和数据打交道的
    2、所以叫model，那么通常情况下，v-vmoel是和input textarea select 这些元素来进行绑定。
    3、它决定了两件事，第一呢，就是用户输入的这个值，我们是不是可以把它反作用到数据模型，当数据模型发生变化，这些选项是不是
    4、能反过来自动去修改它的当前项显示用户输入的状态，这就是所谓的双向数据绑定
    5、表单输入和事件是绑定的两个内容，
7、事件处理
    1、可以使用v-on指令来做事件监听， 那么同学们可以监听一些dom事件，这些事件的名字（click）就会作为v-on的参数被传递，
    2、然后后面是它的回调函数。回调函数声明再methods中，就是标准的使用方式

8、模板语法
    1、vue.js使用了基于html的模板语法的方式来声明页面的样式。同时能够把vue data中声明的这些数据能够动态的展示再页面中
    2、插值文本
    3、使用v-bind这个指令，然后呢给它传递一个参数，这个参数会在冒号后面去指定，等号后面是它具体的值，大家把动态的变量
    4、放在里面去，一旦你使用v-bind指令，这个东西将会变成动态的值，也就是双引号里面，看起来像静态的，它其实绑定的是data里面一个值
    5、如果要去页面内容去绑定一个普通的文本的插值或者是绑定一个属性值
9、样式class绑定
    1、用户会有一个这么一个选中的效果
    2、:class={},对象的形式，还有数组，现在想要动态的指定一个对象，这个对象的key决定了将来哪个类的名称就是这个active
    3、那么这个active要不要加呢，取决于它后面的表达式到底是true还是false，
    4、selectedCourse，如果这个值和我当前遍历的这个值是同一个，则我认为它应该加上active，
10、神奇的模板语法
    1、vue会把编写的这些模板转换成渲染函数，那么这个渲染函数将来的目标是要为了能够生成虚拟dom,所以我们叫虚拟dom的渲染函数
    2、结合响应系统，vue能够智能的计算出最少的需要重新渲染多少组件，并把dom操作次数减少到最少。
    3、我们再次执行渲染函数，得到一个全新的这样一个虚拟dom,那么在新旧dom之间做这个比对，是不是就可以知道真正的dom操作
    4、这个过程看起来很复杂，
    5、赋值购物车，代码，当它结束它这个初始化，这些过程之后，我们在这个选项里面，app.$options里面，可以拿到我们编译器
    6、生成的这个渲染函数。这就是刚才给大家介绍到的这个虚拟dom渲染函数。
    7、把#app内部删除掉，写一个render(){},把渲染dom函数放进去，和原先效果一样。
11、计算属性和监听器
    1、计算属性
        1、在实际工作中，如果模板中出现了很复杂的这样的计算表达式，一般情况下你都需要计算属性的方式，把它写到下面的配置项
        2、计算属性有缓存，如果值没有发生变化，则页面不会重新渲染
        3、为什么不把total写到methods，就是因为这个缓存性，这个值写到methods，不管这个值也没有变化，每次都会重新计算
        4、只要这个值没有变，那么total的值永远都是哪个值，他也不会重新渲染
    2、监听器
        1、默认情况下watch初始化不执行，我想让它立刻执行，把immediate设置为true，这个表示立即执行一次
        2、下面还有个选项叫做deep，观察深层次对象的变化
    3、到底使用哪一个
        1、从简洁性上看，如果能使用computed实现，大家就用computed，因为这种方式它具有缓存性
        2、而watch有立即执行问题，而且还要额外的声明属性，要不然我们就没有办法完成它的功能
        3、如果使用选项的方式，看起来过于复杂了，
        4、语境上说，如果一个值变化了，我可以做一些事情，是不是不止这一个事情，影响多个值
        5、而计算属性，如果有一个值，是由其它值得来的，一旦这些值发生变换，不管是其中的任何一个值，我都要变。
        6、适合多个值影响一个值的情形。在实际工作中，一般都是其它值得变化导致一个最新值得产生
        7、不适合用wathc
            1、firstname变了，我要把这两个值拼成fullname，
            2、lastnaem变了，我也要变，特别啰嗦，是不是就不太适合，
            3、但是什么情形适合，如果firstname变了，我会影响这个值，也会影响那个值，没有这个lastname这个情形，
            4、一个值会影响其它多个值，这个时候用它。
            5、还有就是大家如果在做一些异步操作，或者开销很大得这些操作得时候，大家就适合用监听器了
        8、什么时候适合用watch
            1、这是一个问答程序，用户在输入框里输入问题，如果我发现用户得问题发生变化了
            2、我要去远程得服务器上去请求一下，这个问题得最新得答案，大家可以想一下，这个是异步得请求，非常得消耗资源
            3、那如果用户在这个input里面，疯狂得进行敲击，每一次键盘得输入都会发送一个请求，一个非常可怕得请求风暴
            4、是不是就爆发了，很有可能把我们得程序就卡死了
            5、这个时候就为了避免请求风暴，一般情况下，我们会做一个防抖，会做一个debounce,
            6、引入了ladash这个库里得debouce方法，
12、生命周期
    1、概念
        每个vue在创建得时候都要经过一系列得初始化过程，例如，需要设置数据监听，编译模板，将实例挂载到dom，并在数据变化时
        更新dom，称为vue实例得生命周期
    2、使用生命周期得钩子
        在vue实例得生命周期过程中会运行一些叫做生命周期钩子得函数，这给用户在不同阶段添加自己代码得机会。
    3、模拟接口
        1、数据已经初始化了，但是我们什么时候调用这个接口去访问呢，在实际开发过程中，有两个生命周期得钩子比较常用
        2、一个叫组件得创建钩子，还有一个钩子叫做mounted，
        3、created 组件实例已创建，虽然没有挂载，它自己得数据，以及老爹传下来得数据都可以放心大胆得去访问
        4、由于没有挂载，这些数据还没有转换成真实得dom，dom元素不存在
        5、mounted，将我们前面写得所有得渲染函数执行之后得到得虚拟dom转换成真实dom，也就是说大家在mounted中可以访问到真实得dom元素了
        6、你不要认为这个时间点早，你看到得这个界面可能会早，没有哪个区别呀，实际上我们访问数据花销的时间远远大于它初始化挂载的时候，所以没有实质上的区别
        7、new vue的时候，创建了当前组件的根实例，创建了整个应用程序的根实例，然后呢，是一系列子组件，子组件里面这些子的组件，子的实例都会去创建
        8、首先要做的事情是什么呢，是一些数据的准备，像生命周期，比如我这个生命周期主要是一些这些特别属性的创建
        9、以后我们会跟大家深入的介绍，像老爹的引用，$parent孩子的引用$children，一些跟生命攸关的，那你出生了，肯定得你得知道你爹是谁，但是你还不知道你孩子是谁
        10、但是这些变量，它们得初始化已经做好了，事件得监听，等等
        11、那么接下来是beforecreate得钩子，所以这个时间点是非常早得，以至于开发中很少用到它
        12、再然后是初始化，注入，校验，就是一系列数据得传入，再这个阶段呢，我们会有从来自父组件注入得一些特别得数据，或者是父辈，祖辈传过来得，我们还可以做一些
        13、相关得校验工作，比如说这些数据也没有冲突呀，跟我当前得data，或者property也没有冲突呀，最后，这些数据全部准备就绪了。才会created
        14、接下来会执行挂载逻辑，这是内部去执行得，大家不用关心
        15、我们找到这个宿主了，然后我把当前这些数据结合着我写得模板变成dom,就算完成了
        16、完成之后，就要执行挂载，就是到了dom得追加操作了，我希望把我得内容追加到这个宿主元素上。比如说咱们在界面中写得这个#demo,
        17、在我执行一系列得这个转换过程之前，我会先before mount，通知一下大家，我准备去干这个事了，但是现在还没有去做转换
        18、但是，当我把这些事情都做完之后，大家可以看到，vm.$el,也就是这个dom,元素实际上已经转换完成了，它转换完成之后，会触发这个mounted，会通知用户，
        19、说现在可以访问dom,你可以放心大胆得更新dom，访问dom,也就是说到这，挂载是咱们挂载是完毕得，初始化流程结束。这是第一阶段。
        20、第二阶段，就是这个无限得循环，只要这个组件，它一天不死，不消失，不被删除掉，那么它就处在这个循环过程，不停得在监控咱们这个数据得更新，一旦数据发生更新
        21、准备做更新之前，先beforeupdate,那么等我把所有得更新操作做完，dom操作更新完，我再通知用户，updated
        22、所以，你要再更新之前先记录一下，这个状态，你要beforeupdate，反之，你要看到更新之后得结果，你要再updated这个钩子里去做事情
        23、那么用户手动得掉destroy，当前得组件实例，这个时候也不是立刻销毁，销毁之前，再给大家一点机会，你还可以做一些事情，在这你还可以访问组件实例
        24、比如说，把程序中得定时器取消，销毁子组件，以及事件监听器，等等一些可能造成内存泄漏得东西，把它先解除掉
        25、那么真正销毁完毕得事件是destroyed,
        26、我们在用组件得时候，涉及到组件得缓存，keep-alive,是否销毁它，那么这个时候呢，
13、组件
    1、概念
        1、组件是可复用得vue实例，带有一个名字，我们可以在一个通过new vue创建得vue得根实例中，把这个组件作为自定义元素来使用
    2、定义组件，
        1、父组件传递属性，子组件自定义事件，父组件监听
        2、coutse-list，这个组件它不关心数据来源，它只关心怎么去显示，所以在这里面用属性得方式来给它传递一个courses这么一个属性
        3、这个变量它本身还是在我们当前根组件去维护，然后我们只需要把它作为参数传递给这个course-list ,将来让它在里面去使用
        4、父子之间最简单得沟通是通过属性得方式来传递值给它去显示
        5、那么下一步我们很可能会遇到一些特别得交互得情况，比如说我得子组件可能要跟我得父组件产生一些数据通信，我发生了一些变化，我要告诉你，这时候父组件做一些
        6、相应得变化响应，那么自定义组件自定义事件以及它得监听就是这种方式得一个实现方式
        7、我们假设，这个东西将来明显得要做什么事情呢，在它得内部，用户会交互，比如说会拍个回车，点个新增，那这个时候，我们是不是会通过某种方式，告诉老爹要去新增
        8、一个东西，并且把这个新增得数据给我们传递出来，那它传递得数据，老爹必须知道，这就涉及到了自定义事件的派发和监听过程了
    3、自定义组件双向绑定
        1、course这个变量我确实不想在子组件中维护，它可能和其它各种各样的数据都是在父组件中一起维护的，这时候，我只是想把变量传给你，交给你去维护
        2、但是最终要使用的那个人还是这个父组件本身，v-model="course",由我自己来维护这个course，但是修改却是里面的人，这个组件本身
        3、自定义组件默认是不支持的，首先要明确一件事情，语法糖v-model最终会转换成 :value="course" @input="oninput",
        4、同时，（语法糖v-model）它还表示一个属性的传递，叫value的传递，这个回调函数里面具体的逻辑实际上是这样的，它希望内部派发的这个事件传递的就是那个最新的要变更的值
        5、然后呢，我在这里做成一个赋值，其实我做的事情是，@input="course=$event",$event是固定的名字，表示传递出来的参数，这个参数我把赋值给当前的course变量
        6、所以v-model="course" 最终会变成 :value="course" @input="course=$event",我们就可以知道在我们在course-add的内部，我们要做的事情，其实第一就是
        7、我们要派发一个默认的input事件，并且要把最新的值传递出来作为参数，这是我在内部要做的事情
        8、我在course-add这个内部呢，要接收一个属性叫value，这个value实际上是我course-add用来去持有的这么一个值
        9、但是我不去改变它，我只是派发事件，怎么去改变，怎么赋值，由父组件来决定
        10、让组件本身变得无状态话， 这个是组件定义得过程中大家应该注意得这个事情
14、插槽
    1、概念
        1、对话框得内容显然我将来在用得时候，是在父组件中去指定得，但是这块内容，我将来是要把它显示到message组件得内部得，这个就是内容分发
        2、我现在要在外面提供内容，但是我要分发到里面指定得位置，这就是内容分发技术
        3、vue中得内容分发是插槽，这个名字非常得形象，它有点像电脑上得插槽，usb得接口，我流出这个位置，我得内容是不确定得，但是由你来决定得
        4、你把你得内容通过这个插槽传递给我就可以了，这个就是它得概念，
    2、麻烦的内容分发
        1、 @click="$emit('close',false)加上一个自定义组件得派发，于是乎这里要做得事情是,派发一个自定义事件，告诉老爹，要传递一个值，这个值就是把这个变成false，
        2、直接写表达式，不需要再这里method，要传一个事件，这个事件就叫close事件，然后再把这个值传出去，false，把show这个变量变成false，
        3、不希望说把传进来得这个值，混淆了，到底谁在改，只能老爹改，依照单项数据流得原则，所以我现在只是派发一个事件，让老爹去改，把这个值告诉它。
        4、现在这个编程模式就显得很啰嗦，我在派发，老爹这边呢，还要去处理， @close="show=$event"
    3、利用syc简洁的内容分发
        1、语法上显得很啰嗦，sync修饰符，:show.sync="show" 这表示将来会把它展开成一个事件，这个事件叫做 @update:show=""
        2、就是将来要传出来得那个参数我要赋值给show这个变量， @click="$emit('update:show',false)",子组件自定义事件就规定死了。
    4、匿名插槽
        1、因为在这个message里面，我们传入的内容是非常固定的，就是默认内容，但是如果将来，在这message有多部分内容，不止这个默认内容，
    5、具名插槽
        1、这个时候就需要具名插槽，把指定的内容放到指定的位置
        2、这里首先要通过template方式，来区分出来它的内容的名字，声明一下，这个具名之前的默认内容，就放在没有名字的template
        3、现在我还需要一个标题，那我再来一个，怎么区分这两个template，肯定要有一个名字，用v-slot：
        4、它是通过参数的形式来指定名字，指令的参数用冒号来指定，title，代表将来那个插槽里面的名称 <template v-slot:title></template>
        5、默认的名字，其实是一个语法糖，它其实也有v-slot定义，它的名字叫做default，
        6、在子组件中，<slot name="title"></slot>,将来这块就会被替换成外面的那个template，当然我可以在这里设置默认的内容，
        7、比如说写个默认标题，将来用户没有指定，则用这个，如果指定了，则把这个替换掉
    6、作用域插槽，其实就是在插槽上加一个上下文
        1、在父组件这里头，我定义的内容其实都是由父组件的作用域来决定的，包括这里面的恭喜二字
        2、比如说我现在在这里加上一个变量，叫title，获取的场所应该是获取当前message的这个父组件中去查找的
        3、也就是说这个title大家伙把它定义的位置是，这个根实例里面这个title
        4、那现在有一个特殊的需求，这个值呢，它不是来自当前的上下文，而是来自我们message的子组件，那应当如何获取这个值呢
        5、这个使用方式就是作用域插槽了，我们取而代之应该怎么做呢，
        6、v-slot:title="slotProps",在这里赋一个值
        7、这个值叫临时的上下文，你随便起名 
        8、然后你要做的事情是，在子组件中去指定这个值，那么这是一个上下文，同学们可以在可以直接通过上下文访问这个slotProps.title，
        9、<slot name="title" title="来自子组件的title">默认标题</slot>
        10、上下文就切换了，取决于使用场景，就是你这个值到底是来自内部还是外部，决定了你要不要用作用域插槽
15、组件化实践
    1、优点
        可以增加代码的复用性，可维护性，和可测性
    2、使用场景：
        通用组件，实现最基本的功能，按钮组件，输入框组键，布局组件
        业务组件，完成具体的业务，具有一定的复用性，例如登录组件，轮播图
        页面组件，组织应用各部分独立内容，需要时在不同页面组件间切换，例如列表页，详情页
    3、如何使用组件
        1、定义：vue.component(),components 选项
        2、分类：有状态组件，functional abstract
        3、通信：props $emit()/$on(), provide/inject,$children/$parent/$root/$attrs/$listeners
        4、内容分发<slot>,<template>,v-slot
        5、使用及优化：is,keep-alive,异步组件
    4、组件的本质
        1、vue中的组件经历如下过程
            1、组件配置=》vuecomponent实例=》render()=》virtual DOM=>dom
            2、所以组件的本质是产生虚拟的dom
        2、过程详解
            1、组件大家平常写的只是配置，只是对象
            2、但是这个过程中vue内部到底做了什么，是中间这三部，大家是看不到的
            3、因为你写了配置，最终呢希望看见dom,但是实际上vue内部替你做了三件事
            4、首先它把你写的组件配置转化成了vuecomponent实例，构造函数
            5、这个构造函数之后，又通过方式把它new出来，变成实例，实例里面会有render方法，
            6、render方法怎么来的，前面给大家讲过，你写的模板会转换成render方法，
            7、render方法在合适的时间去执行获得虚拟dom
            8、虚拟dom又通过更新的过程转换成真实dom
            9、所以隐藏在内部的这一部分是vue替你做的。
            10、你应当知道这个过程，最后你应该知道组件的本质就是产生虚拟dom
16、必会api，数据相关
    1、foo:{foo:'foo'},后面又添加了一个属性，foo:{foo:'foo',bar:'bar'}
    2、通过编程的方式给这个foo追加了一个另外一个属性叫做bar,你给它放了一个bar属性，然后你希望它能在界面中动态的变更
    3、显示出来，并且能够在以后变化过程中也会动态的变更，但是你会发现一个奇怪的现象，那么能够动态变更响应式的
    4、其实只有一开始你在声明的这个foo属性，后来在动态添加的这个bar属性，是没有办法动态响应式的
    5、这个其实是和vue去处理数据初始化过程中，这个数据处理方式是又关系的，
    6、如果后续动态的在里面追加一个属性，并确保这个属性同样是响应式的，这个时候请你用vue.set这个api来做
    7、那下面通过一个例子来展示Vue.set这个api的具体使用方式
        1、 this.courses.forEach((c) => {
                    c.price=this.price;
                });
        2、然后输入框里输入100,发现不再好用了。因为这个新添加的价格它不是响应式的，纵使你改了这个值，纵使现在这个数据已经是100
        3、但是界面中却没有更新，要么你在这里输出一下，要门在控制台打印一下，要门你点一下，你会发现，因为我点的时候，是不是会改咱们的样式
        4、这个样式会让界面重新刷新，于是它会按照最新的值去计算，最新的值其实就是100，现在的化，我们怎么解决这个问题
        5、我们batchUpdate的时候，这里要使用官方提供的Vue.set(c,'price',this.price)
    8、Vue.delete
        1、我们平常delete obj['propetry']你这样删除，最终界面中是不会响应的
        2、Vue.delete(c,'price')
        3、只不过没有第三个参数
    9、实例方法，这两个同名实例方法是别名，是刚才这两个方法的别名
17、事件相关api
    1、vm.$on.vm表示的是vue的一个具体的实例，不是它的构造函数。用vue的一个实例或者一个组件的实例可以任意的去监听一个事件，派发一个事件
    2、或者是只监听一次，vm.once，或者取消之前的监听vm.$off
    3、vm.$emit用的时候是在组件内部，给老爹，是不是派发事件，我们用this.$emit派发自定义事件
    4、vm.$on用的不多，因为我们可以在模板中@的方式来进行监听，也就是说你的监听是写在模板中的，你可能会写成@test="callback"这个回调函数
    5、但是大家都用编程的方式来写的化，都用
        vm.$on('test',function(msg){console.log(msg)})
    6、监听事件是写在父组件中的，这个事件的监听者其实是事件的派发者，事件的监听者和派发者是同一个实例
    7、而不是我是在子组件中派发事件，在父组件中去监听，我只是用这种语法区分开来
    8、事件总线。通过在vue原型上添加一个vue实例，作为事件总线，既然放在了原型上，哪将来我在任意的组件中，都可以通过this.$bus的方式
    9、来访问到这个vue的实例，现在这个vue实例可以作为所有组件的中间人，在任何的组件中，只要想给其它的组件去传递消息，你都可以用这个
    10、$bus进行emit，当然也可以在其它的组件中，$on这样大家的通信就非常方便了，它会不受到组件间关系的影响
    11、我要批量清除好多消息，
18、组件或元素引用
    1、ref和vm.$refs
       ref被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的$refs对象上。如果在普通的dom元素上使用，引用指向的就是dom元素
       如果用在子组件上，引用就指向组件实例
    2、ref是作为渲染结果被创建的，在初始渲染时不能访问它们
    3、$refs不是响应式的，不要试图用它在模板中做数据绑定
    4、当v-for用于元素或组件时，引用信息将是包含在dom节点或组件实例的数组
19、vue动画触发方式
    1、vue在插入、更新或者移除dom时，提供多种不同的方式的应用过度效果
    2、动画方式
        2、可以使用transition或者时animation，过度或者动画
        3、使用animate.css
        4、在过度钩子函数中使用JavaScript直接操作dom
        5、也可以使用velocity.js动画库，来实现更加复杂的动画
    3、css动画
        1、在外层加上transition标签，<transition name="fade"
        2、在里面包装的div元素的上面将来会动态的追加类，这个类名叫什么呢，有那么56个类名称，但是关键的只有那么两三个
        3、将来会动态的在这上面加的名字是什么呢，会叫fade
        4、动画的进入或者离开这样的关键字，进入呢，叫enter，离开呢，叫leave，如果这个动画呢，还没进去之前，
        5、比如说我们上舞台上开始表演，这叫演员进场了，那在进场之前，是不是有一个后场呀，在幕后等待的这个过程
        6、所有动画一般会有两个状态，一个开始状态，一个是进入入场之后的，一个是结束状态，这叫关键帧动画
        7、一个起始和结束的两个时间点，它还没有进去之前叫做fade-enter,进入之后呢，我们叫它激活，fade-enter-active
        8、这两个状态vue都会在合适的时候把它加进去，
        9、fade-enter,入场前的状态， .fade-enter{opacity:0},
        10、一开始是看不到的，接下来要给这个动画，定义一个过度的定义fade-enter-active
        11、它在舞台的整个生命周期这个过程中，实际上都会受到这个类的影响，fade-enter这个类其实是非常短的，只有那么一针
        12、那么当它设置完值之后，就会立刻进入到active，这个fade-enter会消失，会被删掉，然后active会被激活
        13、所以在这个过程中，最佳应用是什么呢，是设置它的transition或者是animation制类的,而在fade-enter-to定义结束态
        14、我要做transition的属性是，transition:opacity
        15、用多长时间呢，用0.5s来对它进行一个定义，这是一个最简单的入场动画这个设定呀
        16、其实就已经完成了，
        17、离场动画，离场最后一阵，fade-leave-to
        18、离场过程中，fade-leave-active
    4、使用css动画库
        1、怎样和动画库结合起来，在应用动画的时候，它的类名称是很特别的，它跟哪个vue的默认行为是不一样的，所以意味着这些动画在触发的时候
        2、这些类的名称是不是需要自定义，因此我们现在需要知道两个点，
        3、先来看一下自定义过度类名称，我们可以选的过度类的名称，大概有以下这几种，而且还需要知道它们的优先级，其实是
        4、比普通的类名的优先级是高的，这个时候它的优先级肯定是能覆盖一下它默认生成的这些类的
        5、我们之前指定的是这个name，现在我不再需要了，取而代之的是我需要去把这个激活的时候这个类我来指定一个animate，css它要求的这个类的名称
        7、在animate，它都需要我们提供那些特别类的名称，就想现在这个效果，将来需要指定怎样一个名称，你至少应该指定两个，一个叫animated,叫动画
        8、还有一个类就是当前提供的这个名字，也就是这两个组合起来会是大家看到的这个效果，那我希望是两个类的名称
        9、比如说我现在看上的是这个入场动画，而不是说现在已经在场内了，找一个entrance ,bouncein，这个是一个类的名称
        10、enter-active-class="animated bounceIn"
        11、另外一个叫做leave-active-class="animated bounceOut"
        12、也就是说呢，整个动画的设计过程大家不用操心了，只是合适的时间点把这个类名给它加上或者移除就可以了
    5、js动画
        1、首先大家得知道vue提供给我们js得钩子，
        2、before-enter：动画开始前得
        3、enter:动画之中得
        4、after-enter动画结束之后得
        5、enter-cancelled退出动画得钩子
        6、离开得这四个钩子和刚才这四个是完全对应得
        7、用js来做这件事，需要触发回流，其实无外乎就是我们希望浏览器进行一次重新对布局得一些计算，那么发生这种情况呢
        8、是界面中有尺寸发生变化，不是简单得说颜色上得变化，背景色得变化，这是叫重绘，不是叫重排，它不是一个机制
        9、那比如说，我现在只是象征性得访问一下这个offsetHeight;你这要这么一访问，就能触发浏览器这个回流得行为，它就会重排
        10、那接下来你这个修改，它就会重新计算，这个动画理论上来说就能激活它
        11、可以引入
    6、列表过度 
        1、列表过度得方式，主要得方式呢，要引入一个新得组件它叫transition-group
        2、通常情况下，把v-for,这个循环得元素给包起来
        3、相当于说我呢将来会把这个transition-group展开成n个transition，每个transition包括着一个单独得div，也就是我们将来
        4、渲染出来得这个div，那么这样得化，以后每个元素它是不是都可以增加一个transition，从原来上来说，是这样
20、过滤器
    1、被用于一些常见得文本格式化
    2、插值绑定前面有一个变量，你现在需要一个管道符号，然后把这个格式话得函数在后面去调用，去执行，这个就是我们所说得过滤器函数
    3、在今天得例子当中，它就是把这个message转换成大写或者小写之类的规则
    4、那么同样我们可以在v-bind这样的绑定指令去使用这个管道符号的语法
    5、这是插值语法中或者属性绑定中可以同时去使用
    6、过滤器有两种，一种是全局的，一种是局部的
    7、全局的Vue.filter('Currency')
    8、一般过滤器都是一个工厂函数，我们传入一个值，返回一个值，，所以呢后面不再像其它组件是一个对象，
    9、取而代之的是一个函数，一般情况下大家可以在这声明一个函数，然后呢这个函数会接收一个值，比如说我将来用来修饰的，过滤的这个值
    10、这个输入值，然后呢，将来再return这个值，这是它最简单的一个写法，这是全局的方式
    11、另外一个是局部的方式，大家可以在组件中加上filters,是一个复数呀，因为我们在一个组件中这个过滤器呢可能有多个
    12、加入说过滤器叫做currency，他是一个函数，它将来return一个值，它接收一个值，接收的这个值就是将来过滤的这个值
    13、当然我们还可以接收一些参数，举个例子，我现在想在前面加上中文的这么一个符号然后我再把我这个value放进去，有了currency这个过滤器之后呢
    14、大家就不需要明文的再这里写上这个东西了
    15、然后我们可以直接给这个值用管道符号去修饰，修饰完之后呢，要用咱们下面声明的这个叫currency过滤器
    16、我现在给大家展示的是没有参数的形式，它第一个默认参就是前面的这一部分，将来会自动的去做转换
    17、下面是传参的问题，再这个例子中呢，指定一下这个符号，不能让它去写死，这样的化就显得没有价值，比如说我们再这里加上一个symbol，给它一个默认值
    18、这样的用户如果不传递symbol，如果传了就用传递的这个值，这里呢，就当函数去调用，这样我们就可以传参了，请注意，应该是从它之后，第二位开始
21、自定义指令
    1、比如说我们有一些复用的功能，这些复用的功能呢，是对咱们的普通dom元素来进行操作的时候，我们可以写一些自定义的指令
    2、大家一定要明白自定义指令的使用场景，也就是说你要做一些底层dom操作的时候，因为我们vue从它的设计理念上来讲是数据驱动
    3、一般情况下，尽量不要去接触底层dom操作，如果要做，那就要用自定义指令的方式，去做这件事
    4、实现自定义指令，指令的名字叫directive，然后，同学们给它起一个名字，叫focus，后面是对象，配置对象
    5、这里面需要一些具体的钩子函数，最典型最常用的是insertd，这个钩子函数的化，接收一个dom元素，就是将来这个指令所附加的哪个dom元素
    6、它再mounted之后呢，是不是就会有dom，那这个el就是哪个dom，我就可以对它进行额外的dom操作了，el.focus()方法
    7、是不是就完成了我想做的任务了，这是最简单的一个指令的演示。既然是全局的定义，再任何的组件中都可以去使用
    8、不再inserted里面写的化就不能确定我这个父节点
    9、更新，由于后续的我这个数据的变更，导致我们的当前的这个自定义指令它是不是也会跟着一起去被更新，被调用
    10、钩子函数的参数，el，第一个参，指令所绑定的元素，可以用来直接操作dom
    11、我还需要知道第二个参数，就是这个bindings,非常重要
    12、若指定的用户角色和当前角色不匹配则删除当前的指令绑定的元素，也就是这个toolbar
22、渲染函数
    1、vue推荐在大多数情况下使用模板来创建你的HTML，然而在一些场景中，你真的需要javascript的完全编程的能力，这时
    2、你可以用渲染函数，它比模板更接近编译器
    3、渲染函数的作用是在将来程序进行更新，它再次执行，从而得到最新的这个虚拟dom，
    4、render函数它接收一个参数，这个参数全名叫createElement,叫创建元素，会返回一个VNode这样一个元素
    5、我们称之为虚拟dom,这个元素呢，它就是一个原生的js对象，可以描述我们的dom结构，那么将来的化，在后续的这个虚拟dom的比对中，来产生它的作用
    6、这个方法它本身接收三个参数，第一个参数，我么可能传递标签的名字或者是组件的名字，或者是一个配置对象，还有呢，我要渲染的这个组件或者标签
    7、要传递一些参数，数据，我们传第二个参，它如果有孩子，我们传递第三个参，用子节点数组来描述
    8、我们来实现一个标题组件
    9、我想把它改造成一个拿渲染函数来写，而不是写到咱们模板里头，，使用render方法实现heading组件 
    10、我们呆会希望创建一个heading，跟它用法有点类似，在这插入一个默认插槽，就可以了，呆会我希望和它实现相同的功能
    11、这个heading它本身是要实现一个render 方法，我们知道render方法本身接收一个createElement,在社区里面，大家习惯性的把它简写成h函数
    12、其实这是有来头的，h函数虚拟dom在底层，使用的算法snabbdom,在这个算法里头，它生成虚拟dom的那个方法，就叫h
    13、我们使用这个heading的时候，我们希望它怎么用呀，这里面绑定了一些内容是吧
    14、
23、函数式组件
    1、如果你的组件，它不管理状态，也没有监听别人传给它的状态，也没有生命周期的方法，如果是这种情况，你可以把它标记为functional:true
    2、好处是什么呢，好处是它不在有状态了，也就是说不会再做数据响应式了，它也没有实例，没有上下文，显得是不是更加清亮了
    3、第一个变化就是设置functional:true
    4、render函数会接收第二个参数，我们不再存在this了，所以我们的参数必须通过render函数传递，
    5、属性获取的变化，const {icon,title,level}=context.props
    6、插槽变为context.children
24、混入
    1、比如说在组件中，有一个方法，这个方法很常用，除了当前组件，另外的组件中也会用到
    2、最简单的方式把这个方法提取出来单独放到一个公用的地方，将来呢，大家想用的时候，把它注入进来，然后可以直接用
    3、大家能想到的是，在这个程序里，大家用import的方式或者script的方式把它引进来，但是这样存在一致性的问题
    4、你在用的时候，只能够调这个方法名，而且你要把当前组件的实例传进去，才能操作它，显得很怪异
    5、混入对象里面，就像一个组件的各种选项，你可以随便设置，我在这个例子当中，我设置了一个create，我还设置了一个methods
    6、表示什么呢，将来这个项，我会把它进行一个合并，和我希望混入的那个组件进行一个合并，
    7、那将来这个component它定义的时候它引入了这个myMixin，那么就算它没有created，可是由于我们做了混入，将来这个组件在调用的时候
    8、它实际上是会调这个created，也就是说它会自动执行hello方法，它也能找到混入进来的这个方法
    9、而且最奇妙的是，混入之后，在这，将来上下文就变成了组件实例，我可以非常大胆放心的去使用this，来表示组件实例
25、插件
    1、插件是vue进行扩展的终极方案，我们前面说的想定义指令，自定义组件，自定义过滤器，自定义混入，等等所有这些东西
    2、那么其实不适合去分发，什么意思呢，就是说这些东西将来如果需要把它放到github npm上， 想要发给别人，让别人去用
    3、最佳的方式应该是用插件的形式来组织，因为插件是最安全最好最有效的方式
    4、别人引入的时候，如果重复引，也可以规避，而且在插件里面，也可以很好的组织你这些功能
    5、下面我们来看插件它的一些简单的声明和使用的方式，插件完成的功能有一下几点，
    6、我们在工作中用到的一些，最常用的像router vuex这些东西都是典型的插件，它们很可能实现了其中的一两个
    7、甚至更多，全部
    8、如果你想做一个插件，你必须实现一个install的方法，比如说你现在声明一个对象，你这个对象上必须实现一个install方法
    9、那么这个install方法将来会被咱们vue的构造函数去调用，那么咱们就可以有效的和它进行交互了
    10、你看install的签名，两个参，一个参是vue的构造函数，还有一个是你可能需要的参数
    11、我在这里面就可以做很多事情了
    12、比如我可以直接在vue上挂静态方法，也可以声明一些全局的像指令呀，过滤器呀，我也可以混入
    13、这里我拿不到组件实例，只能配置全局资源，
    14、还有一种就是，大家可以在prototype上加原型方法，这个的化，将来我们在任何组件里面是不是都可以访问到这个方法
    15、让别人直接引这个heading呢，它没有一个有效的这个引入机制，就不太方便去分发，它的最佳的方式，比如说大家可以把它做成一个插件
26、vue cli (https://blog.csdn.net/dengdongxia/article/details/87923329)
    1、通过这个命令行的接口，我们可以执行一些自动化的方式来插件管理项目，所以是平常同学们开发项目必须的呀
    2、我们需要它最重要的原因是我们之前写的这个项目太缺乏一些系统性的工程管理
    3、如果我们引入自己玩，完全可以，但是大家想一想，我这里洋洋洒洒写了好几百行代码，将来可能没有任何的方式去这个优化它
    4、压缩它，提高用户的下载速度，如果我现在是一个团队在编写这个代码，也完全没有办法维护
    5、集中在一起，今天我提交，明天你提交，是不是大家会有各种各样的冲突，我这个代码里面还有很多不适合上生产的地方
    6、比如说大家在开发过程中，一致在用template这种字符串模板，它是带着编译器的，它将来的体积会非常的大，开发的过程中效率也会很低
    7、没有任何代码提示，我们必须把这个项目完全改造成工程化项目
    8、vue-cli，我们先从快速原型开发给大家体验一下
    9、如果说你不需要创建一个大型的项目，就需要看到一个用vue的方式去写的一个组件，它最终生成的样子
    10、给你的领导或者给你的客户去看，用这种方式就是最佳不过了
    11、比如说有一个单页面的hello.vue，像快速的看到这个页面的结果，你不需要去创建项目，你只需要使用刚才大家提到的这个东西
    12、cli-service-global这个东西，全局安装一下它，然后你会多上两个指令，就是veu server 和vue build 这两个指令
    13、一个是用来测试，看效果，一个是用来打包，
    14、我们先来看效果，vue serve Hello.vue
    15、它会先起一个测试服务器，然后我们这个时候再去点击，我是不是就可以看到这个页面的效果了
    16、cnpm i -g @vue/cli    cnpm i -g @vue/cli-service-global 必须装这两个
    17、vue serve Hello.vue
    18、我要真正的开发一个完整的项目，我创建一个新的基于vue的项目，大家可以使用vue create这个命令来创建
    19、当前项目，vue create xx
    20、这个时候命令行的接口会提供一些问题，让你回答，主要是一些项目的选项，我如果现在不是很了解这些东西，有一个最佳的实践方式就是
    21、直接选这个default，就可以了。但是我想深入了解一下，具体的选项。我很了解它的这个具体细节
    22、我完全可以选择下面的自定义，我要不要用ts，要不要加上pwa的特性，或者是路由器和状态管理
    23、还有像css的预处理器，大家熟悉的sass,less 你打算用可以把它勾上
    24、或者你要做测试，但是前提条件你要很了解你要做的这些事情到底是什么，在今天的这个例子中，如果这些都不选的化
    25、只勾选当前Babel，编译的这个选项，以及llinter代码质量检测这个选项，其实就是刚才大家看到的那个默认选项
    26、后续我还要选一下做eslint的一些方式，我是说很严格，如果有lint我就过不去呢
    27、还是说在命令行给我一个简单的提示，我的项目还是能看到它的效果，这个取决于你对自己的这个项目组的要求程度，
    28、如果你要求很严格，任何代码上的不允许出现错误的情况只要发生了，我不希望用户这个项目可以跑起来
    29、其实这是对程序员最严格的要求，也是让它避免出现代码质量问题的一个最好的方式，但编写过程中会有一些体验上的影响
    30、还有一些就是格式化工具，这些有一些细节上的差异，我们不去做过多的赘述呀，大家去选，包括我这个执行代码检测 lint的时间点
    31、是保存之后立刻lint，还是说我在提交的时候才去做lint，它是有一些区别的。另外的化，就是配置文件的具体位置，大概是这些
    32、这些是默认配置。假设同学们把这些选项都选完，我们就会经历一个项目的基本结构的创建，依赖的安装，这样的一个过程需要等上几分钟时间
    33、甚至把我一些webpack配置的脚本给你输出出来，都非常直观，inspect这个命令非常的好用，这个命令其实还是走的咱们这个命令
    34、vue-cli-service inspect --mode production
    35、它最终是不是会把当前的这个项目的webpack的这么一个配置给你做一个完整的输出呀
    36、vue-cli从3.0开始，我们已经完全看不到这个webpack配置了，好处是同学们可能 不需要要求那么多的webpack的相关知识
    37、就可以做很多很多事情，但是缺点是大家变得是不是越来越傻瓜了。因为我们不了解内部的东西
    38、所以我建议同学们一开始它最终生成的这个webpack的配置是一个什么样的，里面的loader ,里面的插件都是怎样的
    39、我们后续再做一些配置，更新，管理我们都会更有这个办法和方法，
27、项目迁移
    1、git push --set-upstream origin dev
    



















 */